﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Serialization;
using System.IO;

namespace UserInterface
{
    public partial class MainUI : Form
    {
        public MainUI()
        {
            this.StartPosition = FormStartPosition.CenterScreen;
            InitializeComponent();
            this.lbl_carNumber.Text = this.CarScroll.Value.ToString();
        }

        Map map = new Map();
        bool add = false;
        bool delete = false;
        bool move = false;
        Image img;
        PictureBox toBeMoved;
        DateTime startTime;
        DateTime stopTime;
        DateTime timePaused;
        bool simWasLive = false;       
        //---------------MENU BUTTONS-----------------------------------------//
        private void btnMove_Click(object sender, EventArgs e)
        {
            this.toBeMoved = null;
            this.move = true;
        }

        private void chkbxDelete_CheckedChanged(object sender, EventArgs e)
        {
            if (chkbxDelete.CheckState == CheckState.Checked)
                this.delete = true;
            else
                delete = false;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.AddExtension = true;
            this.openFileDialog1.DefaultExt = ".tjk";
            this.openFileDialog1.Filter = "Grid only (*.tjk)|*.tjk|Whole simulation (*.tjsm)|*.tjsm|All files (*.*)|*.*";
            string extension = "";

            if (map.getNumberOfCrossings() > 0)
            {
                if (MessageBox.Show("Do you want to save the current work?", "Notification!", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                { btnSave_Click(null, null); }
                    
            }

            if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                extension = openFileDialog1.FileName.Substring(openFileDialog1.FileName.Length - 4, 4);
                if (extension != ".tjk" && extension != "tjsm")
                {
                    MessageBox.Show("Please select a file with the extension: \".tjk\" or \".tjsm\"","Can't Load..");
                    return;
                }
                resetAll();
                
                try
                {
                    this.map = (Map)Serializer.DeSerializeObject(this.openFileDialog1.FileName);
                    getPictures();
                }
                catch(SerializationException ex)
                {
                    MessageBox.Show("Failed to open, because: " + ex.Message);
                }                
            }
        }

        /// <summary>
        /// Runs after load and loops through crossings.
        /// Assignes the corresponding picture
        /// Maps the crossing to the corresponding picturebox
        /// </summary>
        private void getPictures()
        {
            Crossing temp;
                 // i=1 as starting index and <7 as max crossings
            for (int i = 1; i < 7; i++)
            {
                temp = map.getCrossing(i);
                
                if (temp != null)
                {
                    int indx = temp.getIndex();
                    temp.mapPicturebox((PictureBox)this.Controls[this.Controls.IndexOfKey("pbx_" + indx.ToString())]);
                    temp.pbox.Image = temp.im; 
                }
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (map.getNumberOfCrossings() > 0)
            {
                this.saveFileDialog1.AddExtension = true;
                this.saveFileDialog1.Filter = simWasLive ? "All Simulation Files (*.tjsm)|*.tjsm" : "Crossing Placement Files Only (*.tjk)|*.tjk";
                              
                
                if (this.saveFileDialog1.ShowDialog() == DialogResult.OK)
                {

                    btnPause_Click(null, null);
                    try
                    {
                        string filename = this.saveFileDialog1.FileName;
                        //SaveFileDialog saveAs = new SaveFileDialog();
                        //saveAs.InitialDirectory = Application.StartupPath;
                        //saveAs.FileName = Application.ProductName;

                        //if (extension == "tjsm")
                        //{
                        //    object[]
                        //}
                        //else

                        Serializer.SerializeObject(filename, map);
                    }
                    catch (SerializationException ex)
                    {
                        MessageBox.Show("Failed to save, because: " + ex.Message);
                    }
                    finally
                    {
                        this.btnPlay_Click(null,null);
                    }
                }
                
            }
            else
            {
                MessageBox.Show("There is nothing to be saved!");
            }
        }

        bool crossing1 = true;
        private void btnCrossing1_MouseDown(object sender, MouseEventArgs e)
        {
            add = true;
            img = Rsrc_Images.Type1_SMALL;
            crossing1 = true;
        }

        private void btnCrossing2_MouseDown(object sender, MouseEventArgs e)
        {
            add = true;
            img = Rsrc_Images.Type2_SMALL;
            crossing1 = false;
        }

        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            this.lbl_carNumber.Text = this.CarScroll.Value.ToString();
        }

        /*----------------------------------------------------------------------*/


        // ------------TOOL STRIP EVENTS----------FORM EVENTS----------------------------//
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to exit?", "Exit program", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                this.Close();
            else
                return;            
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.btnSave_Click(sender, e);
        }        

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.btnOpen_Click(sender, e);
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            /*
             * RESETS CURRENT WORK
             * DELETES EVERYTHING
             * RERUNS THE PROGRAM AS NEWLY STARTED
             * 
             */
            if (MessageBox.Show("Your current work will be lost.", "Create a new simulation", MessageBoxButtons.OKCancel) == System.Windows.Forms.DialogResult.Cancel)
                return;
            else
                resetAll();
        }

        void resetAll()
        {
            this.stopSimulationGuiControls();
            this.lbl_time.Visible = false;
            this.pbx_1.Image = null;
            this.pbx_2.Image = null;
            this.pbx_3.Image = null;
            this.pbx_4.Image = null;
            this.pbx_5.Image = null;
            this.pbx_6.Image = null;
            this.add = false;
            this.move = false;
            this.chkbxDelete.CheckState = CheckState.Unchecked;
            this.img = null;
            this.toBeMoved = null;

            for (int i = 1; i < 7; i++)
            {
                //this.pictureBox_Paint("dsvadva" + i, null);
                map.DeleteCrossing(i);
            }//this.tmr_GenerateCars.Stop;
        }

        private void statisticsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Statistics t = new Statistics(this.map);
            t.Icon = this.Icon;
            t.StartPosition = FormStartPosition.CenterScreen;
            t.Show();
        }


        private void editCarDirectionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Edit edt = new Edit(this.map, 'c');
            edt.Icon = this.Icon;
            edt.StartPosition = FormStartPosition.CenterScreen;
            edt.ShowDialog();

            //if(edt.DialogResult == System.Windows.Forms.DialogResult.OK )
            //{
            //    Map m = edt.getResults();
            //    if (m != null)
            //        map = m;
            //}
        }
       
        private void editPedestriansToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Edit edt = new Edit(this.map, 'p');
            edt.Icon = this.Icon;
            edt.StartPosition = FormStartPosition.CenterScreen;
            edt.ShowDialog();

            //if (edt.DialogResult == System.Windows.Forms.DialogResult.OK)
            //{
            //    Map m = edt.getResults();
            //    if (m != null)
            //        map = m;
            //}
        }

        private void editTrafficLightsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Edit edt = new Edit(this.map, 'l');
            edt.Icon = this.Icon;
            edt.StartPosition = FormStartPosition.CenterScreen;
            edt.ShowDialog();

        //    if (edt.DialogResult == System.Windows.Forms.DialogResult.OK)
        //    {
        //        Map m = edt.getResults();
        //        if (m != null)
        //            map = m;
        //    }
        }

        private void manualToolStripMenuItem_Click(object sender, EventArgs e)
        {
            HelpForm help = new HelpForm();
            help.Icon = this.Icon;
            help.Show();
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            About abt = new About();
            abt.Icon = this.Icon;
            abt.ShowDialog();
        }

       /*---------------------------------------------------------------------------------*/
       
        

        
    //-------------MOUSE DOWN EVENT OF THE PICTUREBOXES THAT HOLD THE CROSSINGS-----------------------------//    
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (add && img != null)
            {
                addCrossing((PictureBox)sender);
                add = false;
                return;
            }
            else if (add && img == null)
            {
                MessageBox.Show("select Crossing First");
                add = false;
                return;
            }

            if (delete)
            {
                deleteCrossing((PictureBox)sender);
                chkbxDelete.CheckState = CheckState.Unchecked;
                return;
            }

            if (move && toBeMoved == null)
            {
                toBeMoved = (PictureBox)sender;
                return;
            }
            else if (move && toBeMoved != null)
            {
                movePbx((PictureBox)sender);
                return;
            }
        }


        private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
        {
            if (add && img != null)
            {
                addCrossing((PictureBox)sender);
                add = false;
                return;
            }
            else if (add && img == null)
            {
                MessageBox.Show("select Crossing First");
                add = false;
                return;
            }

            if (delete)
            {
                deleteCrossing((PictureBox)sender);
                chkbxDelete.CheckState = CheckState.Unchecked;
                return;
            }

            if (move && toBeMoved == null)
            {
                toBeMoved = (PictureBox)sender;
                return;
            }
            else if (move && toBeMoved != null)
            {   
                movePbx((PictureBox)sender);
                return;
            }
        }

        private void pictureBox3_MouseDown(object sender, MouseEventArgs e)
        {
            if (add && img != null)
            {
                addCrossing((PictureBox)sender);
                add = false;
                return;
            }
            else if (add && img == null)
            {
                MessageBox.Show("select Crossing First");
                add = false;
                return;
            }

            if (delete)
            {
                deleteCrossing((PictureBox)sender);
                chkbxDelete.CheckState = CheckState.Unchecked;
                return;
            }

            if (move && toBeMoved == null)
            {
                toBeMoved = (PictureBox)sender;
                return;
            }
            else if (move && toBeMoved != null)
            {
                movePbx((PictureBox)sender);
                return;
            }
        }

        private void pictureBox4_MouseDown(object sender, MouseEventArgs e)
        {
            if (add && img != null)
            {
                addCrossing((PictureBox)sender);
                add = false;
                return;
            }
            else if (add && img == null)
            {
                MessageBox.Show("select Crossing First");
                add = false;
                return;
            }

            if (delete)
            {
                deleteCrossing((PictureBox)sender);
                chkbxDelete.CheckState = CheckState.Unchecked;
                return;
            }

            if (move && toBeMoved == null)
            {
                toBeMoved = (PictureBox)sender;
                return;
            }
            else if (move && toBeMoved != null)
            {
                movePbx((PictureBox)sender);
                return;
            }
        }

        private void pictureBox5_MouseDown(object sender, MouseEventArgs e)
        {
            if (add && img != null)
            {
                addCrossing((PictureBox)sender);
                add = false;
                return;
            }
            else if (add && img == null)
            {
                MessageBox.Show("select Crossing First");
                add = false;
                return;
            }

            if (delete)
            {
                deleteCrossing((PictureBox)sender);
                chkbxDelete.CheckState = CheckState.Unchecked;
                return;
            }

            if (move && toBeMoved == null)
            {
                toBeMoved = (PictureBox)sender;
                return;
            }
            else if (move && toBeMoved != null)
            {
                movePbx((PictureBox)sender);
                return;
            }
        }

        private void pictureBox6_MouseDown(object sender, MouseEventArgs e)
        {
            PictureBox pbx = (PictureBox)sender;

            if (add && img != null && pbx.Image == null)
            {
                addCrossing(pbx);
                add = false;
                return;
            }
            else if (add && img == null)
            {
                MessageBox.Show("select Crossing First");
                add = false;
                return;
            }

            if (delete)
            {
                deleteCrossing(pbx);
                chkbxDelete.CheckState = CheckState.Unchecked;
                return;
            }

            if (move && toBeMoved == null && pbx.Image !=null)
            {
                toBeMoved = pbx;
                return;
            }
            else if (move && toBeMoved != null && pbx.Image == null)
            {
                movePbx(pbx);
                return;
            }

            //pbx = null;
            //this.add = false;
            //this.move = false;
            //img = null;
            //this.toBeMoved = null;

        }

        private void CarScroll_Scroll(object sender, EventArgs e)
        {
            this.lbl_carNumber.Text = this.CarScroll.Value.ToString();
        }

        /*------------------------------------------------------------------------------------------*/

        

        
        //-----------------DEVELOPER DEFINED FUNCTIONS----------------------------------//
        /// <summary>
        /// Moves a crossing to a new position by deleting the previous one and creating a new one
        /// </summary>
        /// <param name="pbx">The <b>picturebox</b> to move the crossing to</param>
        void movePbx(PictureBox pbx)
        {
            // If user tries to move the picturebox
            // in the same position do nothing
            if (pbx == toBeMoved)
            {
                toBeMoved = null;
                move = false;
                return;
            }
            if (toBeMoved.Image != null && pbx.Image ==null)
            {
                img = toBeMoved.Image;
                addCrossing(pbx);
                deleteCrossing(toBeMoved);
                
            }
            toBeMoved = null;
            move = false;
          //  else { MessageBox.Show("You cannot move an empty cell", "Move error"); }
        }

        List<Lane> lanes = new List<Lane>();
        
        /// <summary>
        /// Creates a crossing to the specified picturebox and adds it to the Map 
        /// </summary>
        /// <param name="pbx">The <b>picturebox</b> that will hold the crossing</param>
        void addCrossing(PictureBox pbx)
        {
            if (pbx.Image == null)
            {
                char tmp = pbx.Name[pbx.Name.Length - 1];
                int index;
                int.TryParse(tmp.ToString(),out index);

                pbx.Image = img;

                if (!crossing1)
                {                    
                    img = null;
                    map.AddCrossing(new CrossingType2(pbx.Location, index, pbx));

                    //pbx.Paint += new PaintEventHandler(this.pictureBox_Paint);
                    //map.GenerateCars(10);
                }
                /* 
                 * Create the crossing Class
                 * Add it to the Map
                 * Calculate the neighbours
                 * Fill in the data from the neighbours
                 * Calculate from where to generate cars
                 */
                else
                {
                    //pbx.Paint += new PaintEventHandler(this.pictureBox_Paint);
                    map.AddCrossing(new CrossingType1(pbx.Location, index,pbx));
                }

            }

        }

        /// <summary>
        /// Deletes the crossing from the current Map
        /// </summary>
        /// <param name="pbx">The <b>picturebox</b> that holds the crossing </param>
        void deleteCrossing(PictureBox pbx)
        {
            char tmp = pbx.Name[pbx.Name.Length - 1];
            int index = int.Parse(tmp.ToString());
            /*
             * Delete this crossings references from other neighbours
             * Delete recalculate neibhours (for the other crossings)
             * Delete the crossing
             * 
             */

                pbx.Image = null;
                try
                {
                    pbx.Paint -= new PaintEventHandler(map.getCrossing(index).getallCars2Draw);
                }
                catch (NullReferenceException) { }
                //calculate the neigbhour references again
                map.DeleteCrossing(index);
                pbx.Refresh();
        }

        private void pbx_1_MouseMove(object sender, MouseEventArgs e)
        {
            this.lbl_XY.Text = "X+Y: " + e.Location;
        }

        private void btnPedestrians_Click(object sender, EventArgs e)
        {
            map.GeneratePedo();
        }

        /// <summary>
        /// Starts the simulation and 
        /// the timer that generates the cars
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPlay_Click(object sender, EventArgs e)
        {
            if (map.getNumberOfCrossings() < 1)
            { 
                MessageBox.Show("First place crossings on the grid.", "Can't Start!");
                return;
            }

            simWasLive = !simWasLive;

            map.startSimulation();
            if(!this.tmr_GenerateCars.Enabled)
                this.tmr_GenerateCars.Start();
            this.btnCar_Click(null, null);
            this.startSimulationGuiControls();
        }
        /// <summary>
        /// disables the controls needed when the simulation start
        /// </summary>
        private void startSimulationGuiControls()
        {
            this.btnCrossing1.Enabled = false;
            this.btnCrossing2.Enabled = false;
            this.btnMove.Enabled = false;
            this.btnPlay.Enabled = false;
            this.btnPause.Enabled = true;
            this.chkbxDelete.Enabled = false;
            this.btnOpen.Enabled = false;
            this.lbl_time.Text = "Started at: ";
            this.startTime = DateTime.Now;
            this.lbl_time.Text += DateTime.Now.ToString("h:m:s");
            this.lbl_time.Visible = true;
        }

        /// <summary>
        ///  Stops the simulation
        ///  and the timer that generates the cars
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            simWasLive = false;
            map.stopSimulation();
            if (this.tmr_GenerateCars.Enabled)
               this.tmr_GenerateCars.Stop();
            this.stopSimulationGuiControls();
             
        }
        /// <summary>
        /// enables the controls needed when the simulation stops
        /// </summary>
        private void stopSimulationGuiControls()
        {
            this.btnCrossing1.Enabled = true;
            this.btnCrossing2.Enabled = true;
            this.btnMove.Enabled = true;
            this.btnPlay.Enabled = true;
            this.chkbxDelete.Enabled = true;
            this.btnPause.Enabled = true;
            this.btnOpen.Enabled = true;
            this.stopTime = DateTime.Now;
            TimeSpan timeLasted = stopTime - startTime;
            this.lbl_time.Text = "Time lasted: " + timeLasted.Hours.ToString()+":"+timeLasted.Minutes.ToString()+":"+timeLasted.Seconds.ToString();
        }

        /// <summary>
        /// Pauses the simulation and 
        /// stops timer that generates the cars
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPause_Click(object sender, EventArgs e)
        {
            simWasLive = false;

            map.pauseSimulation();
            if (this.tmr_GenerateCars.Enabled)
                this.tmr_GenerateCars.Stop();
            this.pauseSimulationGuiControls();
        }
        /// <summary>
        /// enables the controls needed when the simulation pauses
        /// </summary>
        private void pauseSimulationGuiControls()
        {
            this.btnPlay.Enabled = true;
            this.btnPause.Enabled = false;
        }

        /// <summary>
        /// Enables the timer tha generates the cars and also 
        /// calculates how many cars to add per tick of the timer
        /// The value is taken from the slider on the GUI
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCar_Click(object sender, EventArgs e)
        {
            if (!tmr_GenerateCars.Enabled)
                this.tmr_GenerateCars.Start();
            this.cars2Add = this.CarScroll.Value;
            try
            {
                cars2Add = cars2Add/2;
                if (cars2Add == 0)
                    cars2Add = 1;
            }
            catch (Exception) { cars2Add = 1; }
            tmr_GenerateCars_Tick(null, null);
        }
        /// <summary>
        /// Timer interval to run and number of cars to add
        /// </summary>
        int interval = 20000, cars2Add;

        private void tmr_GenerateCars_Tick(object sender, EventArgs e)
        {
            //btnCar_Click(null, null);
            interval -= 7500;
            if (interval >= 0)
            {
                //try
                //{
                //    cars2Add = cars2Add / 4;
                //}
                //catch (Exception) { cars2Add = 1; }
                map.GenerateCars(cars2Add);
            }
            else
            {
                interval = 20000;
                cars2Add = this.CarScroll.Value;
            }
        }

              
      
        /*--------------------------------------------------------------------------------------------------*/
    
    
    }
}
